<?php
namespace App\Library;

use Redis;
class RedisCommon
{

    private $rq_conf;


    public $redisq;


    public function __construct()
    {
        $this->rq_conf = config('database.redis.default');
        $this->redisq = new Redis();
        $this->redisq->pconnect($this->rq_conf['host'], $this->rq_conf['port'], 2);
    }

    /**
     *
     * @param string $key
     */
    private function _get($key)
    {
        $popRet = $this->redisq->rPop($key);
        if ($popRet == false) {
            return '';
        } else {
            return unserialize($popRet);
        }
    }


    /**
     *
     * @param string $key
     * @param mixed $data
     */
    private function _set($key, $data)
    {
        return $this->redisq->lPush($key, serialize($data));
    }

    public function info()
    {
        return $this->redisq->info();
    }

    /**
     * 从队列取数据，可取多条
     * @param string $key queue name
     * @param integer $num record count
     * @return string|multitype:NULL
     */
    public function qget($key, $num = 1)
    {
        if (!$key || $num < 1) {
            return "";
        }
        if ($num == 1) {
            return $this->_get($key);
        }
        $results = array();
        for ($i = 0; $i < $num; $i++) {
            $r = $this->_get($key);
            if (!$r) {
                break;
            }
            $results[] = $r;
        }
        return $results;
    }


    /**
     * 入队列 ， 可多条
     * @param string $key queue name
     * @param mixed $data data
     * @param boolean $multi 是否多条
     * @return boolean
     */
    public function qset($key, $data, $multi = false)
    {
        if (!$key || !$data) {
            return false;
        }
        if ($multi && is_array($data)) {
            foreach ($data as $d) {
                $this->_set($key, $d);
            }
        } else {
            $this->_set($key, $data);
        }
        return true;
    }


    /**
     * 取队列里数据
     * @param $key
     * @param int $start
     * @param int $end
     * @return array|mixed|string
     */
    public function lrange($key, $start = 0, $end = -1)
    {
        $data = $this->redisq->lRange($key, $start, $end);
        if ($data) {
            if (is_array($data)) {
                $r = array();
                foreach ($data as $item) {
                    $r[] = unserialize($item);
                }
                return $r;
            } else {
                return unserialize($data);
            }
        } else {
            return "";
        }
    }

    public function set_unhandled($key, $value, $timeout = 60)
    {
        return $this->redisq->setex($key, $timeout, $value);
    }

    public function setex($key, $value, $timeout = 60)
    {
        $value = serialize($value);
        return $this->redisq->setex($key, $timeout, $value);
    }


    public function setnx($key, $value)
    {
        return $this->redisq->setnx($key, serialize($value));
    }


    public function get_unhandled($key)
    {
        $value = $this->redisq->get($key);
        if ($value !== false)
            return $value;
        else
            return false;
    }


    public function get($key)
    {
        $value = $this->redisq->get($key);

        if ($value)
            return unserialize($value);
        else
            return false;
    }

    public function mget_unhandled($keyArray)
    {
        $mget = $this->redisq->mget($keyArray);
        $mget = array_map(function($item){
            return json_decode($item, true);
        }, $mget);
        $result = array_combine($keyArray, $mget);

        return $result;
    }

    /**
     * 批量获取多个key值
     * @param  [array] $keyArray [key数组]
     * @return [array] $result   [返回key--value关联数组]
     */
    public function mget($keyArray)
    {
        $mget = $this->redisq->mget($keyArray);
        $mget = array_map(function($item){
            return unserialize($item);
        }, $mget);
        $result = array_combine($keyArray, $mget);

        return $result;
    }



    public function set($key, $val, $timeout = 60)
    {
        if ($timeout <= 0) {
            return false;
        }
        return $this->redisq->setex($key, $timeout, serialize($val));
    }


    public function delete($key)
    {
        return $this->redisq->delete($key);
    }


    /**
     * 判断对象是否锁定，如果没有锁，即加锁
     * @param $obj  对象 可以为任意类型 除resource类型外
     * @param int $locktime 锁定秒数
     * @return bool true 已经锁定  false 没有锁定，并锁定
     */
    public function is_lock($obj, $locktime = 3)
    {
        $key = md5(json_encode($obj));
        if ($this->get($key)) {
            return true;
        } else {
            $this->setex($key, $obj, $locktime);
            return false;
        }
    }


    /*
     * 向名称为$key的集合中添加元素$member
     * @param $key
     * @param $member
     * @return $int the number of elements added to the set
     */

    public function sadd($key, $member)
    {
        return $this->redisq->sAdd($key, $member);
    }


    /*
     * 向名称为$key的有序集合中添加元素$member
     * @param $key
     * @param $score
     * @param $member
     * @return $int the number of elements added to the set
     */
    public function zadd($key, $score, $member)
    {
        return $this->redisq->zAdd($key, $score, $member);
    }


    /*
     * 删除名称为$key的集合中的元素$member
     * @param $key
     * @param $member
     * @return $int The number of elements removed from the set
     */

    public function srem($key, $member)
    {
        return $this->redisq->sRem($key, $member);
    }


    /**
     * 判断$member是否是名称为$key的集合的元素
     * @param $key
     * @param $member
     * @return boolean
     */
    public function sismember($key, $member)
    {
        return $this->redisq->sIsMember($key, $member);
    }


    /**
     * 求交集
     * @param $key1
     * @param $key2
     * @return array
     */
    public function sinter($key1, $key2)
    {
        return $this->redisq->sInter($key1, $key2);
    }


    /**
     * 获取集合中的所有成员
     * @param $key
     * @return array
     */
    public function smembers($key)
    {
        return $this->redisq->sMembers($key);
    }


    /**
     * 随机取得集合中的一个成员（不删除）
     * @param $key
     * @return string
     */
    public function setrand($key)
    {
        return $this->redisq->sRandMember($key);
    }


    /**
     * 集合数量
     * @param $key
     * @return int
     */
    public function scount($key)
    {
        return $this->redisq->sCard($key);
    }


    /**
     * key是否存在
     * @param $key
     * @return int
     */
    public function exists($key)
    {
        return $this->redisq->exists($key);
    }


    /**
     * 返回集合1中存在但不在集合2中存在的元素
     * @param $key1
     * @param $keys
     * @return array
     */
    public function sunique($key1, $key2)
    {
        return $this->redisq->sDiff($key1, $key2);
    }


    /**
     * 返回有序集合中指定范围的元素
     * @param $key
     * @param $from
     * @param $to
     * @return array
     */
    public function zrange($key, $from, $to)
    {
        return $this->redisq->zRange($key, $from, $to);
    }


    public function lPush($key, $value)
    {
        return $this->redisq->lPush($key, $value);
    }


    public function lPop($key)
    {
        return $this->redisq->lPop($key);
    }


    public function rPush($key, $value)
    {
        return $this->redisq->rPush($key, $value);
    }


    public function rPop($key)
    {
        return $this->redisq->rPop($key);
    }


    public function lSize($key)
    {
        return $this->redisq->lSize($key);
    }
    
    public function listRange($key, $start, $end) {
        return $this->redisq->lRange($key, $start, $end);
    }


    public function setexpire($key, $ttl)
    {
        return $this->redisq->expire($key, $ttl);
    }


    public function getKeys($pattern)
    {
        return $this->redisq->keys($pattern);
    }

    /**
     * 加一操作
     */
    public function incr($key){
        return $this->redisq->incr($key);
    }

    /**
     * 减一操作
     */
    public function decr($key){
        return $this->redisq->decr($key);
    }

    /**
     * 加操作
     */
    public function icnrBy($key, $increment){
        return $this->redisq->incrBy($key, $increment);
    }

    /**
     * set一个整数
     */
    public function setInt($key, $value, $timeout = 0){
        return $this->redisq->set($key, intval($value), $timeout);
    }

    /**
     * get一个整数
     */
    public function getInt($key){
        $result = $this->redisq->get($key);

        return $result;
    }

    /**
     * 查看key的过期时间
     */
    public function ttl($key){
        return $this->redisq->ttl($key);
    }

    public function exec(){
        return $this->redisq->exec();
    }

    public function pipeline(){
        return $this->redisq->pipeline();
    }

    /**
     * 加操作
     */
    public function incrBy($key, $increment){
        return $this->redisq->incrBy($key, $increment);
    }

    public function hset($key, $hashKey, $value)
    {
        return $this->redisq->hSet($key, $hashKey, $value);
    }

    public function hmset($key, $hashKeys){
        return $this->redisq->hMset($key, $hashKeys);
    }

    public function hget($key, $hashKey){
        return $this->redisq->hGet($key, $hashKey);
    }

    public function hmget($key, $hashKeys){
        return $this->redisq->hMGet($key, $hashKeys);
    }

    public function hgetall($key){
        return $this->redisq->hGetAll($key);
    }

    public function hsetnx($key, $hashKey, $value)
    {
        return $this->redisq->hSetNx($key, $hashKey, $value);
    }
    
    public function hexists($key, $hashKey)
    {
        return $this->redisq->hExists($key, $hashKey);
    }

    public function hincrby($key, $hashkey, $value)
    {
        return $this->redisq->hIncrBy($key, $hashkey, $value);
    }

    public function zRangeByScore($string,$start,$end,$array = array())
    {
        return $this->redisq->zRangeByScore($string,$start,$end,$array);
    }

    /**  有序集合分类范围内数量
     * @param $key
     * @param $start
     * @param $end
     */
    public function zCount( $key, $start, $end )
    {
        return $this->redisq->zCount($key, $start, $end);
    }
}
